<template>
  <div class="home">
    <div class="game-box" :class="loading ? '': 'toImg'" id="gameBox" v-loading="loading">
      <Game ref="gameRef" v-if="gameCmp" :gameOver="gameOver" @gameOver="handleGameOver" />
      <div class="bg" v-if="!userStore.account">
        <p class="guide">Control guidelines</p>
        <img class="img" src="../../assets/e0dfe72ca14aec59.png" alt="">
        <el-button type="primary" @click="handleConnect">Connect wallet</el-button>
      </div>
    </div>
    <div class="btn-box" v-if="userStore.account">
      <el-button type="primary" @click="handleReStart">Restart</el-button>
      <el-button :type="gameInfo.score>0?'success':''" :disabled="loading" @click="handleSaveImg">Mint NFT</el-button>
    </div>
  </div>
</template>

<script setup>
import Game from "./Game.vue";
import html2canvas from "html2canvas";
import { NFTStorage, File } from "nft.storage";
import { ElNotification } from 'element-plus'
import { useEthersStore } from '@/stores/modules/providers'
import { ref, getCurrentInstance, onMounted, watchEffect, nextTick } from "vue";

const userStore = useEthersStore()
const loading = ref(false)
const gameOver = ref(true)
const gameInfo = ref({
  score: 0, step: 0, startTime: new Date().getTime(), endTime: new Date().getTime()
})
const gameCmp = ref(true)

const curInstance = getCurrentInstance()
let timer = null
watchEffect(() => {
  if (!userStore.account) {
    gameOver.value = true
  } else {
    handleReStart()
  }
})

const apiKey = import.meta.env.VITE_NFT_STORAGE_KEY
const client = new NFTStorage({ token: apiKey })

async function handleConnect () {
  try {
    await userStore.connect(true)
    clearTimeout(timer)
    gameOver.value && curInstance.ctx.$refs.gameRef.initGame()
    gameOver.value = false
  } catch (error) {
    console.log('[ error ] >', error)
  }
}

async function handleSaveImg () {
  loading.value = true
  await setTimeout(100) // 解决导出图片文字不显示问题
  html2canvas(document.getElementById('gameBox'), { useCORS: true, allowTaint: false }).then(
    (canvas) => {
      canvas.toBlob(async (blob) => {
        let filename = `${new Date().getTime()}.jpg`
        const { score, step, startTime, endTime } = gameInfo.value
        const metadata = await client.store({
          name: 'Game2048',
          description: 'Game2048',
          score: score,
          attributes: [
            {
              trait_type: 'createTime',
              value: startTime
            },
            {
              trait_type: 'endTime',
              value: endTime
            },
            {
              trait_type: 'stepNumber',
              value: step
            },
          ],
          image: new File([blob], filename, { type: 'image/jpg' }),
        })
        const tokenURI = metadata.url.replace(
          'ipfs://',
          'https://ipfs.io/ipfs/'
        )
        mint(tokenURI)
      })
    }
  );
}

async function mint (tokenURI) {
  const gameContract = userStore.instanceContract()
  try {
    const { score, step, startTime, endTime } = gameInfo.value
    const tx = await gameContract.mintItem(userStore.account, tokenURI, score, step, startTime, endTime)
    loading.value = false
    handleReStart()
    ElNotification.success({
      message: 'Pending',
      title: 'Success',
    })
    await tx.wait()
    ElNotification.success({
      message: 'Mint success',
      title: 'Success',
    })
  } catch (error) {
    loading.value = false
    console.log('[ error ] >', error)
  }
}

async function handleReStart () {
  gameOver.value = false
  gameInfo.value = {
    score: 0, step: 0, startTime: new Date().getTime(), endTime: new Date().getTime()
  }
  gameCmp.value = false
  await setTimeout(100) // 解决导出图片文字不显示问题
  gameCmp.value = true
  await nextTick()
  curInstance.ctx.$refs.gameRef && curInstance.ctx.$refs.gameRef.initGame()
}
async function handleGameOver (val) {
  gameInfo.value = val
  gameOver.value = true
}

onMounted(() => {
  if (userStore.account) {
    handleReStart()
  }
})

</script>

<style lang="less" scoped>
.home {
  max-width: 1000px;
  margin: 0 auto;
  overflow: hidden;
  position: relative;
  .game-box {
    width: 450px;
    height: 505px;
    margin: 40px auto;
    position: relative;
    .bg {
      position: absolute;
      left: 0;
      top: 55px;
      width: 450px;
      height: 450px;
      border-radius: 10px;
      overflow: hidden;
      background-color: rgba(0, 0, 0, 0.6);
      z-index: 999;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      .img {
        width: 120px;
        margin-bottom: 20px;
      }
      .guide {
        color: #fff;
      }
      :deep(.el-button) {
        width: 320px;
        height: 64px;
        font-size: 20px;
      }
    }
    &.toImg {
      // 解决导出图片文字显示不出来问题
      :deep(.appear) {
        transform-origin: center center;
        animation: zoom 0.1s 0.2s backwards;
      }
    }
  }

  .btn-box {
    display: flex;
    width: 450px;
    margin: 0 auto;
    align-items: center;
    justify-content: center;
    .el-button {
      width: 200px;
      height: 44px;
    }
  }
}

@keyframes zoom {
  0% {
    opacity: 0;
    transform: scale(0);
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}
</style>